package org.snia.server.security;

import java.io.IOException;
import java.util.Date;

import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.naming.NamingException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.snia.util.ServiceUtils;

public class EjbSecurityIntercepter {

	@AroundInvoke
	public Object Authorization(InvocationContext ctx) throws Exception {
		long startTime = System.currentTimeMillis();
		
		try {
			System.setProperty("java.security.auth.login.config", "file:E:/TSpace/jtadf-cloud-router/test_src/com/alpha/cloud/test/jaas_sample");
			LoginContext lc = null;
			try {
				lc = new LoginContext("CSESigner", new MyCallbackHandler());
			} catch (LoginException le) {
				System.err
						.println("Cannot create LoginContext. " + le.getMessage());
				System.exit(-1);
			} catch (SecurityException se) {
				System.err
						.println("Cannot create LoginContext. " + se.getMessage());
				System.exit(-1);
			}
			
			try {
				// attempt authentication
				lc.login();

			} catch (LoginException le) {
				le.printStackTrace();
				System.err.println("Authentication failed:");
				System.err.println("  " + le.getMessage());
			}
			//如果验证失败，则直接返回，不允许进一步操作
			return ctx.proceed();
		} catch (NamingException e) {
			throw e;
		} finally {
			long time = System.currentTimeMillis() - startTime;
			System.out.println("用时" + time + "ms");
		}
	}
}

/**
 * The application implements the CallbackHandler.
 * 
 * <p>
 * This application is text-based. Therefore it displays information to the user
 * using the OutputStreams System.out and System.err, and gathers input from the
 * user using the InputStream System.in.
 */
class MyCallbackHandler implements CallbackHandler {
	@Override
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		String secretKey="Ex6FioaA7c/JlACUeBdmp7Soqm9YwyxKPUWQuATi";
		String date = ServiceUtils.formatRfc822Date(new Date());
		
		int length = callbacks.length;
		TextInputCallback nc = null;
		
		if(length > 0)  nc = (TextInputCallback) callbacks[0];
		String canonicalString = stringToSign("PUT", "http://www.china.com/mycontainer", secretKey,
				date, null);

		String signature = ServiceUtils.signWithHmacSha1(secretKey, canonicalString);
		
		nc.setText("HWS Ex6FioaA7c/JlACUeBdm:" + signature);
		if(length > 1)  nc = (TextInputCallback) callbacks[1];
		nc.setText(date);
		if(length > 2 )	nc = (TextInputCallback) callbacks[2];
		nc.setText("http://www.china.com/mycontainer");
		if(length > 3 )	nc = (TextInputCallback) callbacks[3];
		nc.setText("PUT");
	}
	
	private static <T> String stringToSign(String method, String resourcePath,
			String accessSecureKey, String date, String expires) {
		if (resourcePath == null)
			throw new IllegalArgumentException(
					"Parameter resourcePath is empty");
		
		StringBuilder buf = new StringBuilder();
		buf.append(method + "\n");
		buf.append(resourcePath + "\n");
		buf.append(accessSecureKey + "\n");
		buf.append(date + "\n");

		if (expires != null && expires.length() != 0) {
			buf.append(expires + "\n");
		}
		return buf.toString();
	}
}